package BNS.coloring;

import java.io.File;
import java.util.StringTokenizer;

import BNS.graphs.GraphPack;
import BNS.graphs.Node;
import BNS.plumbing.BNSGameController;
import BNS.plumbing.Library;


/** This is an example class that implements a simple graph coloring game.
	The game is solved when all players have colored their node the same as each of their neighbours. 
	It assumes that the colors are integers in {1,2, ..., colorChoices}. 
	The counterpart class in the client machine is ColoringPersona.
	*/
public class VoterGame extends ConsensusGame {
	/**
   * 
   */
  private static final long serialVersionUID = 1L;
  float payScale;
	float[][] nodePayoff;
	
	/** Used to construct a game, using parameters from a Tokenizer.
		Conventionally, this (and the constructor) are used to build an
		object to be stored in a file and used in a session later.
		*/
	public static BNSGameController build(String dir, StringTokenizer st) {
		BNSGameController game= null;
		try {
			File gpFile= new File(dir,st.nextToken()+".gpack");
			GraphPack gp= Library.getPack(gpFile);
			if (gp==null) return null;
			int time= Integer.parseInt(st.nextToken());
			int colors= Integer.parseInt(st.nextToken());
			float payScale= Float.parseFloat(st.nextToken());
			String payFile= st.nextToken();
			System.err.println("parameters: "+ time +", "+ colors +", "+ payScale +", "+ payFile);
			float[][] payoffs= BNS.plumbing.BuildGames.readRaggedArray(new File(dir,payFile));
			System.err.println("got "+payoffs.length+" rows");
			System.err.println(payoffs[0].length+" and "+payoffs[1].length);
			game= new BNS.coloring.VoterGame(gp,colors,time,payScale,payoffs);
		} catch(Exception e) { System.err.println("problem: "+ e); }
		return game;
		}
	
	/** sole constructor
		@param gp the GraphPack to use in this game
		@param colors the number of different colors to use
		@param time the maximum number of seconds the game will be allowed to run
		@param winPayoff the dollar reward for having your node well-colored
		*/
	public VoterGame(GraphPack gp, int colors, int time, float payScale, float[][] payoffs) {
		super(gp, colors, time, payScale);
		nodePayoff= payoffs;
		System.err.println("nodePayoffs= "+nodePayoff);
		for (int i=0; i<nodePayoff.length; i++) {
			for (int j=0; j<nodePayoff[i].length; j++)
				System.err.print("#"+nodePayoff[i][j]);
			System.err.println();
			}
		}
	
	/** These inits override those in ConsensusGame. */	
	protected void otherInits(float pay) {
		colormapIsIdentity= true;//false;
		payScale= pay;
//		nodePayoff= (float[][])grpk.getProperty("nodePayoffs");
		}
	
	public String getTitle() { return "Voter Game"; }
	
	/** gives a long description of this game; used to inform supervisor about game choice. */
	public String getInfo() { 
		return getTitle() +" of size "+ getSize() +"\n"
		+" number of colours allowed= "+ colorChoices +"\n"
		+" payScale="+ payScale +"\n"
		+" time allowed="+ timeLimit +"\n"
		+" graphpack info= "+ grpk.getInfo();
		}
	
//	protected boolean solved() { return grpk.graph.colored(false); }
	
//	protected boolean locallySolved(Graph gr) { return gr.locallySolved(false,state); }
	
	/** returns a measure of "social welfare" indicating how the group as a whole is doing */
	protected int getProgress() { return grpk.graph.satEdges(false); }
	
	/** returns a string defining how dollar rewards are awarded. 
		(Not part of BNSGameController.)
		TODO: consider retiring this in favour of static final variable */
	public String getPayoffDefn(Node node) { 
		int nIdx= node.getIndex();
		payoffDefn= "Your payoff is "
			+ form(nodePayoff[nIdx][0]) +" if everyone's color is blue, "
			+ form(nodePayoff[nIdx][1]) +" if everyone's color is red, "
			+" otherwise $0.";
		return payoffDefn;
		}
	private String form(float pay) {
		return String.format("$%.2f",pay);
		}
	
	public float getPayoff(int nodeIdx, int time) { 
		boolean flag= currentProgress==perfection;
		System.err.println("node ("+ nodeIdx +")"+(flag?" ":" not ")+"solved");
		if (!flag) return 0.0f;
		if (nodeStates[nodeIdx].colorInt==0) return nodePayoff[nodeIdx][0];
		if (nodeStates[nodeIdx].colorInt==1) return nodePayoff[nodeIdx][1];
		return 0.0f;
		}
	
	} // EOC VoterGame
